/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session.stateful;

import entity.AnalyticsEntity;
import entity.BranchEntity;
import entity.ChosenMetricEntity;
import entity.TouristAccountEntity;
import entity.FnBReservationEntity;
import entity.GrouponPaymentItemEntity;
import entity.MealEntity;
import entity.MetricTypeEntity;
import entity.PackagePurchasedEntity;
import entity.PaymentManagementEntity;
import entity.RedemptionPaymentItemEntity;
import entity.ReservationEntity;
import entity.ReservedMealEntity;
import entity.ReservedSetMealEntity;
import entity.ServicePackageEntity;
import entity.SetMealEntity;
import entity.StakeholderEntity;
import entity.TCubeEntity;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import util.entityhelper.AccumulationHelper;
import util.entityhelper.DoubleComparator;
import util.entityhelper.DoubleHelper;
import util.entityhelper.MonthHelper;

/**
 *
 * @author HenryHieuPham
 */
@Stateful
@LocalBean
public class MetricSessionBean {

    @EJB
    ReservationSessionBean reservationSessionBean;
    @EJB
    BranchSessionBeanStateful branchSessionBean;
    @PersistenceContext
    private EntityManager entityManager;

    public List<FnBReservationEntity> fnBReservation(Long branchId) {
        List<ReservationEntity> list = reservationSessionBean.getReservationListByBranchId(branchId);
        List<FnBReservationEntity> result = new ArrayList<FnBReservationEntity>();
        for (ReservationEntity r : list) {
            if (r instanceof FnBReservationEntity) {
                FnBReservationEntity f = (FnBReservationEntity) r;
                result.add(f);
            }
        }
        return result;
    }

    public List<FnBReservationEntity> dateReservation(Date date, Long branchId) {
        List<FnBReservationEntity> list = fnBReservation(branchId);
        List<FnBReservationEntity> result = new ArrayList<FnBReservationEntity>();
        for (FnBReservationEntity f : list) {
            if (f.getDateReserved().compareTo(date) == 0) {
                result.add(f);
            }
        }
        return result;
    }

    public List<String> reservationNumbers(List<FnBReservationEntity> list) {
        int total = 0, show = 0, noshow = 0, confirmed = 0, rejected = 0, cancelled = 0;
        double revenue = 0, deposit = 0.0;
        List<String> result = new ArrayList<String>();
        total = list.size();
        for (Object o : list) {
            FnBReservationEntity f = (FnBReservationEntity) o;
            if (f.getStatus() != null && f.getStatus().equalsIgnoreCase("Show")) {
                show++;
            }
            if (f.getStatus() != null && f.getStatus().equalsIgnoreCase("No Show")) {
                noshow++;
            }
            if (f.getConfirmation().equalsIgnoreCase("Confirmed")) {
                confirmed++;
            }
            if (f.getConfirmation().equalsIgnoreCase("Rejected")) {
                rejected++;
            }
            if (f.getConfirmation().equalsIgnoreCase("Cancelled")) {
                cancelled++;
            }
            deposit = deposit + f.getDeposit();
            revenue += computeRevenue(f);

        }
        result.add(Integer.toString(total));
        result.add(Integer.toString(show));
        result.add(Integer.toString(noshow));
        result.add(Integer.toString(confirmed));
        result.add(Integer.toString(rejected));
        result.add(Double.toString(deposit));
        result.add(Double.toString(revenue));
        result.add(Integer.toString(cancelled));
        return result;
    }

    private double computeRevenue(FnBReservationEntity f) {
        double revenue = 0;
        if (!f.getReservedMeal().isEmpty() && f.getStatus() != null && f.getStatus().equalsIgnoreCase("Show")) {
            for (int i = 0; i < f.getReservedMeal().size(); i++) {
                revenue = revenue + f.getReservedMeal().get(i).getPrice() * f.getReservedMeal().get(i).getQuantity();
            }
        }
        if (!f.getReservedSetMeal().isEmpty() && f.getStatus() != null && f.getStatus().equalsIgnoreCase("Show")) {
            for (int i = 0; i < f.getReservedSetMeal().size(); i++) {
                revenue = revenue + f.getReservedSetMeal().get(i).getPrice() * f.getReservedSetMeal().get(i).getQuantity();
            }
        }
        if (f.getReservedMeal().isEmpty() && f.getReservedSetMeal().isEmpty() && !f.getReservedTable().isEmpty()
                && f.getStatus() != null && f.getStatus().equalsIgnoreCase("Show")) {
            revenue = revenue + f.getDeposit();
        }
        return revenue;
    }

    public TouristAccountEntity getTouristById(Long Id) {
        TouristAccountEntity tourist = entityManager.find(TouristAccountEntity.class, Id);
        return tourist;
    }

    public MealEntity getMealById(Long Id) {
        MealEntity meal = new MealEntity();
        meal = entityManager.find(MealEntity.class, Id);
        return meal;
    }

    public SetMealEntity getSetMealById(Long Id) {
        SetMealEntity setMeal = new SetMealEntity();
        setMeal = entityManager.find(SetMealEntity.class, Id);
        return setMeal;
    }

    public List<AnalyticsEntity> getAnalyticsForStakeholder() {
        Query query = entityManager.createQuery("SELECT a FROM AnalyticsEntity a WHERE a.forStakeholder = true");


        return query.getResultList();
    }

    //Added by Vu
    public AnalyticsEntity[] getAnalyticsByServicePackageId(Long id) {
        ServicePackageEntity pack = entityManager.find(ServicePackageEntity.class, id);
        List<AnalyticsEntity> list = pack.getAnalytic();

        AnalyticsEntity[] result = new AnalyticsEntity[list.size()];

        for (int i = 0; i < result.length; i++) {
            result[i] = list.get(i);
        }

        return result;
    }

    public List<ChosenMetricEntity> getListOfChosenMetricByStakeholderId(long id) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, id);
        return stakeholder.getChosenMetrics();
    }

    public List<MetricTypeEntity> getAllMetricType() {
        Query query = entityManager.createQuery("SELECT m FROM MetricTypeEntity m");
        return query.getResultList();
    }
    //End added by Vu

    /*
     * Purpose: get list of analytics available for stakeholder in this
     * metric type
     */
    public List<AnalyticsEntity> getAnalyticsByTypeForStakeholder(Long id) {
        MetricTypeEntity type = entityManager.find(MetricTypeEntity.class, id);
        List<AnalyticsEntity> list = type.getAnalytic();
        List<AnalyticsEntity> result = new ArrayList<AnalyticsEntity>();

        for (AnalyticsEntity ana : list) {
            if (ana.isForStakeholder()) {
                result.add(ana);
            }
        }
        return result;
    }

    /*
     * Purpose: Save the list of chosen metrics by this stakeholder
     * widgets1: is the first column
     * widgets2: is the second column
     */
    public void saveCustomizedList(long id, List<String> widgets1, List<String> widgets2) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, id);

        List<ChosenMetricEntity> list = stakeholder.getChosenMetrics();

        while (!list.isEmpty()) {
            ChosenMetricEntity m = list.get(0);
            list.remove(m);
            m.getAnalytics().getChosenMetrics().remove(m);
            entityManager.merge(m.getAnalytics());
            entityManager.remove(m);
        }
        entityManager.merge(stakeholder);

        addChosenMetricForStakeholder(stakeholder, widgets1, 0);
        addChosenMetricForStakeholder(stakeholder, widgets2, 1);
    }

    /*
     * Purpose: add all of the metrics chosen by this stakeholder to this column
     */
    private void addChosenMetricForStakeholder(StakeholderEntity stakeholder, List<String> widgets, int colPos) {
        int pos = 0;
        for (String s : widgets) {
            long anaId = Long.valueOf(s.substring(1));
            AnalyticsEntity ana = entityManager.find(AnalyticsEntity.class, anaId);
            ChosenMetricEntity chosen = new ChosenMetricEntity();
            chosen.setColumnPosition(colPos);
            chosen.setListPosition(pos);
            chosen.setStakeholder(stakeholder);
            chosen.setAnalytics(ana);
            entityManager.persist(chosen);
            ana.getChosenMetrics().add(chosen);
            entityManager.merge(ana);
            stakeholder.getChosenMetrics().add(chosen);
            pos++;
        }
        entityManager.merge(stakeholder);
    }

    private void addChosenMetricForTCube(TCubeEntity tCube, List<String> widgets, int colPos) {
        int pos = 0;
        for (String s : widgets) {
            long anaId = Long.valueOf(s.substring(1));
            AnalyticsEntity ana = entityManager.find(AnalyticsEntity.class, anaId);
            ChosenMetricEntity chosen = new ChosenMetricEntity();
            chosen.setColumnPosition(colPos);
            chosen.setListPosition(pos);
            chosen.setTcube(tCube);
            chosen.setAnalytics(ana);
            entityManager.persist(chosen);
            ana.getChosenMetrics().add(chosen);
            entityManager.merge(ana);
            tCube.getChosenMetrics().add(chosen);
            pos++;
        }
        entityManager.merge(tCube);
    }

    /*
     * Returns the list of analytics that can be used by this stakeholder
     */
    public List<AnalyticsEntity> getAnalyticsCanBeUsedByStakeholder(Long id) {
        StakeholderEntity stakeholder = entityManager.find(StakeholderEntity.class, id);

        List<BranchEntity> branchList = stakeholder.getBranches();
        List<AnalyticsEntity> result = new ArrayList<AnalyticsEntity>();

        //go through every branch
        for (BranchEntity branch : branchList) {
            PackagePurchasedEntity pack = branchSessionBean.getCurrentPackagePurchased(branch.getId());
            List<AnalyticsEntity> tempList = pack.getServicePackage().getAnalytic();
            //choose the one with highest service package. We assume that the higher service package is
            //the more analytics it can use
            if (tempList.size() > result.size()) {
                result = tempList;
            }
        }
        return result;
    }

    public List<AnalyticsEntity> getAnalyticsForTCube() {
        Query query = entityManager.createQuery("SELECT a FROM AnalyticsEntity a");
        List<AnalyticsEntity> temp = query.getResultList();

        List<AnalyticsEntity> result = new ArrayList<AnalyticsEntity>();

        for (AnalyticsEntity ana : temp) {
            if (ana.isForStakeholder()) {
                result.add(ana);
            }
        }
        return result;
    }

    public List<ChosenMetricEntity> getListOfChosenMetricByTCubeId(long id) {
        TCubeEntity tcube = entityManager.find(TCubeEntity.class, id);
        return tcube.getChosenMetrics();
    }

    public Double getTotalSalesByDate(Date date) {
        double totalSales = 0.0;
        Query query = entityManager.createQuery("SELECT f FROM FnBReservationEntity f WHERE f.dateReserved = :date");
        query.setParameter("date", date);
        List<FnBReservationEntity> reservations = query.getResultList();
        for (FnBReservationEntity r: reservations) {
            for (ReservedSetMealEntity obj: r.getReservedSetMeal()) {
                totalSales = totalSales + obj.getPrice()*obj.getQuantity();
            }
            for (ReservedMealEntity obj: r.getReservedMeal()) {
                totalSales = totalSales + obj.getPrice()*obj.getQuantity();
            }
        }
        query = entityManager.createQuery("SELECT g FROM GrouponPaymentItemEntity g WHERE g.dateCreated = :date");
        query.setParameter("date", date);
        List<GrouponPaymentItemEntity> grouponPurchases = query.getResultList();
        for (GrouponPaymentItemEntity g : grouponPurchases) {
            totalSales = totalSales + g.getPurchasedGroupon().getGroupon().getOfferedPrice()*g.getPurchasedGroupon().getQuantity();
        }
        return totalSales;
    }
    
    // Added by Cong Dat
    public Double getTotalSalesByPeriod(Date startDate,Date endDate) {
        double totalSales = 0.0;
        Query query = entityManager.createQuery("SELECT f FROM FnBReservationEntity f WHERE f.dateReserved >= :startDate AND f.dateReserved <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<FnBReservationEntity> reservations = query.getResultList();
        for (FnBReservationEntity r: reservations) {
            for (ReservedSetMealEntity obj: r.getReservedSetMeal()) {
                totalSales = totalSales + obj.getPrice()*obj.getQuantity();
            }
            for (ReservedMealEntity obj: r.getReservedMeal()) {
                totalSales = totalSales + obj.getPrice()*obj.getQuantity();
            }
        }
        query = entityManager.createQuery("SELECT g FROM GrouponPaymentItemEntity g WHERE g.dateCreated >= :startDate AND g.dateCreated <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<GrouponPaymentItemEntity> grouponPurchases = query.getResultList();
        for (GrouponPaymentItemEntity g : grouponPurchases) {
            totalSales = totalSales + g.getPurchasedGroupon().getGroupon().getOfferedPrice()*g.getPurchasedGroupon().getQuantity();
        }
        return totalSales;
    }
    
    // Added by Cong Dat
    public Double getTotalSalesByMonth(MonthHelper monthHelper) {
        double totalSales = 0.0;
        //
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        
        Query query = entityManager.createQuery("SELECT f FROM FnBReservationEntity f WHERE f.dateReserved >= :startDate AND f.dateReserved <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<FnBReservationEntity> reservations = query.getResultList();
        for (FnBReservationEntity r: reservations) {
            for (ReservedSetMealEntity obj: r.getReservedSetMeal()) {
                totalSales = totalSales + obj.getPrice()*obj.getQuantity();
            }
            for (ReservedMealEntity obj: r.getReservedMeal()) {
                totalSales = totalSales + obj.getPrice()*obj.getQuantity();
            }
        }
        query = entityManager.createQuery("SELECT g FROM GrouponPaymentItemEntity g WHERE g.dateCreated >= :startDate AND g.dateCreated <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<GrouponPaymentItemEntity> grouponPurchases = query.getResultList();
        for (GrouponPaymentItemEntity g : grouponPurchases) {
            totalSales = totalSales + g.getPurchasedGroupon().getGroupon().getOfferedPrice()*g.getPurchasedGroupon().getQuantity();
        }
        return totalSales;
    }
    
    // Added by Cong Dat
    public Double getTotalTCubeRevenueByMonth(MonthHelper monthHelper) {
        Double tCubeRevenue = 0.0;
        //
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        
        // If this is the current month
        // If this month was in the past - retrieve from PaymentManagement
        Query query = entityManager.createQuery("SELECT p FROM PaymentManagementEntity p WHERE p.startDate >= :startDate AND p.startDate <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<PaymentManagementEntity> list = query.getResultList();
        for (PaymentManagementEntity p: list) {
            tCubeRevenue = tCubeRevenue + p.getTotalPaymentCurrent();
        }
        return tCubeRevenue;
    }
    
    // Added by Cong Dat
    public Integer getNumberOfSubscribersByMonth(MonthHelper monthHelper) {
        Integer numberOfSubscribers = 0;
        // Initialize startDate & endDate
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        //
        Query query = entityManager.createQuery("SELECT p FROM PackagePurchasedEntity p WHERE p.datePurchased >= :startDate AND p.datePurchased <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        numberOfSubscribers = query.getResultList().size();
        return numberOfSubscribers;
    }
    
    // Added by Cong Dat
    public Integer getNumberOfSubscribersByDate(Date date) {
        Integer numberOfSubscribers = 0;
        //
        Query query = entityManager.createQuery("SELECT p FROM PackagePurchasedEntity p WHERE p.datePurchased = :date");
        query.setParameter("date", date);
        numberOfSubscribers = query.getResultList().size();
        return numberOfSubscribers;
    }
    
     // Added by Cong Dat
    public Integer getNumberOfSubscribersByPeriod(Date startDate,Date endDate) {
        Integer numberOfSubscribers = 0;
        Query query = entityManager.createQuery("SELECT p FROM PackagePurchasedEntity p WHERE p.datePurchased >= :startDate AND p.datePurchased <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        numberOfSubscribers = query.getResultList().size();
        return numberOfSubscribers;
    }
    
    // Added by Cong Dat
    public Double getTotalCostOfULPByMonth(MonthHelper monthHelper) {
        Double totalCost = 0.0;
        //
       Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        //
        Query query = entityManager.createQuery("SELECT r FROM RedemptionPaymentItemEntity r WHERE r.dateCreated >= :startDate AND r.dateCreated <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<RedemptionPaymentItemEntity> list = query.getResultList();
        for (RedemptionPaymentItemEntity p: list) {
            totalCost = totalCost + p.getAmountToStakeholder();
        }
        return totalCost;
    }
    
    // Added by Cong Dat
    public Integer getNumberOfActiveStakeholders(MonthHelper monthHelper) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        Query query = entityManager.createQuery("SELECT s FROM StakeholderEntity s WHERE s.activate = :activate AND s.dateRegistered <= :endDate");
        query.setParameter("activate", true);
        query.setParameter("endDate", endDate);
        return query.getResultList().size();
    }
    
    // Added by Cong Dat
    public Integer getNumberOfInactiveStakeholders(MonthHelper monthHelper) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        Query query = entityManager.createQuery("SELECT s FROM StakeholderEntity s WHERE s.activate = :activate AND s.dateRegistered <= :endDate");
        query.setParameter("activate", false);
        query.setParameter("endDate", endDate);
        return query.getResultList().size();
    }
    
    // Added by Cong Dat
    public Integer getNumberOfTouristAccounts(MonthHelper monthHelper) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        System.out.println(endDate);
        Query query = entityManager.createQuery("SELECT u FROM TouristAcct u WHERE u.creationDate <= :endDate");
        query.setParameter("endDate", endDate);
        return query.getResultList().size();
    }
    
    // Added by Cong Dat
    public Integer getNumberOfStaffAccounts(MonthHelper monthHelper) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        Query query = entityManager.createQuery("SELECT s FROM StaffAcct s WHERE s.creationDate <= :endDate");
        query.setParameter("endDate",endDate);
        return query.getResultList().size();
    }
    
    // Added by Cong Dat
    public Integer getNumberOfTouristAccountsByDate(Date date) {
        Query query = entityManager.createQuery("SELECT t FROM TouristAcct t WHERE t.creationDate <= :date");
        query.setParameter("date", date);
        return query.getResultList().size();
    }
    
    // Added by Cong Dat
    public Integer getNumberOfStakeholderAccountsByDate(Date date) {
        Query query = entityManager.createQuery("SELECT t FROM StakeholderEntity t WHERE t.dateRegistered <= :date");
        query.setParameter("date", date);
        return query.getResultList().size();
    }
    
    // Added by Cong Dat
    public Double getRewardingULPPointsByMonth(MonthHelper monthHelper) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth()-1,1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(),1);
        Date endDate = calendar.getTime();
        //
        Query query = entityManager.createQuery("SELECT r FROM FnBReservationEntity r WHERE r.dateReserved >= :startDate AND r.dateReserved <= :endDate AND r.status = :status");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate",endDate);
        query.setParameter("status","Show");
        List<ReservationEntity> list = query.getResultList();
        //
        List<AccumulationHelper> accumulationList = new ArrayList<AccumulationHelper>();
        for (ReservationEntity r: list) {
            accumulationList.add(new AccumulationHelper(r));
        }
        Double totalPoint = 0.0;
        for (AccumulationHelper a: accumulationList) {
            totalPoint = totalPoint + a.getTotalPoint();
        }
        return totalPoint;
    }
    
    // Added by Cong Dat


    // Added by Cong Dat
    public List getMostLeastPopularServicePackageByMonth(MonthHelper monthHelper) {
       
        List<DoubleHelper> list = new ArrayList<DoubleHelper>();
        //
        Calendar calendar = new GregorianCalendar();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth() - 1, 1);
        Date startDate = calendar.getTime();
        calendar.set(monthHelper.getYear(), monthHelper.getMonth(), 1);
        Date endDate = calendar.getTime();
        //
        Query query = entityManager.createQuery("SELECT p FROM PackagePurchasedEntity p WHERE p.datePurchased >= :startDate AND p.datePurchased <= :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);
        List<PackagePurchasedEntity> packagePurchasedList = query.getResultList();
        //
        query = entityManager.createQuery("SELECT s FROM ServicePackageEntity s WHERE s.visibility = :visibility");
        query.setParameter("visibility", true);
        List<ServicePackageEntity> servicePackageList = query.getResultList();

        //
        HashMap<ServicePackageEntity, Integer> map = new HashMap<ServicePackageEntity, Integer>();

        //
        for (ServicePackageEntity s : servicePackageList) {
            int count = 0;
            for (PackagePurchasedEntity p : packagePurchasedList) {
                if (p.getServicePackage().getId() == s.getId()) {
                    count = count + 1;
                }
            }
            map.put(s, count);
        }
        Set<ServicePackageEntity> key = map.keySet();

        for (ServicePackageEntity s : key) {
            list.add(new DoubleHelper(s, (double) map.get(s)));
        }
        //sort
        Collections.sort(list, new DoubleComparator());
        return list;
    }

    public void saveTCubeCustomizedList(Long id, List<String> widgets1, List<String> widgets2) {
        TCubeEntity tCube = entityManager.find(TCubeEntity.class, id);

        List<ChosenMetricEntity> list = tCube.getChosenMetrics();

        while (!list.isEmpty()) {
            ChosenMetricEntity m = list.get(0);
            list.remove(m);
            m.getAnalytics().getChosenMetrics().remove(m);
            entityManager.merge(m.getAnalytics());
            entityManager.remove(m);
        }
        entityManager.merge(tCube);

        addChosenMetricForTCube(tCube, widgets1, 0);
        addChosenMetricForTCube(tCube, widgets2, 1);
    }

    public List<AnalyticsEntity> getAnalyticsByTypeForTCube(Long id) {
        MetricTypeEntity type = entityManager.find(MetricTypeEntity.class, id);
        List<AnalyticsEntity> list = type.getAnalytic();
        List<AnalyticsEntity> result = new ArrayList<AnalyticsEntity>();

        for (AnalyticsEntity ana : list) {
            if (!ana.isForStakeholder()) {
                result.add(ana);
            }
        }
        return result;
    }
    //Hieu-start

    public Double getUpsellingRate(TouristAccountEntity t, StakeholderEntity stakeholder) {
        Double upsellingRate = 0.0;
        Double sum = 0.0;
        Double last = 0.0, average = 0.0;
        Date date;
        System.out.println("tourist " + t.getId());
        List<FnBReservationEntity> reservation = new ArrayList<FnBReservationEntity>();
        reservation = reservationSessionBean.getFnBReservationByStakeholder(stakeholder); // all "show" fnbreservation of stakeholder
        List<FnBReservationEntity> customerReservation = new ArrayList<FnBReservationEntity>(); // fandbreservations of a specific customer only
        System.out.println("session 1");

        for (FnBReservationEntity f : reservation) {
            System.out.println("session 2a");
            System.out.println("Id " + f.getTourist().getId());
            System.out.println("table " + f.getReservedTable().isEmpty());
            if (f.getTourist().getId() == t.getId() && (!f.getReservedMeal().isEmpty()) || !f.getReservedSetMeal().isEmpty()) {
                customerReservation.add(f);
                System.out.println("session 2b" + f.getDateReserved());
            }
        }
        System.out.println("session 3");

        if (!customerReservation.isEmpty()) { //in case returnees just book tables only

            date = customerReservation.get(0).getDateReserved();
            System.out.println("date " + date);
            last = customerReservation.get(0).getDeposit();
            System.out.println("session 4");
            for (FnBReservationEntity f : customerReservation) {
                System.out.println("session 5A");
                double revenue = computeRevenue(f);
                sum = sum + revenue;
                System.out.println("sum " + sum);
                System.out.println("date f " + f.getDateReserved());
                if (f.getDateReserved().compareTo(date) > 0) {
                    System.out.println("session 6A");
                    date = f.getDateReserved();
                    last = revenue;
                    System.out.println("session 6B");
                }
            }

            System.out.println("last " + last);


            average = sum / customerReservation.size();
            System.out.println("average " + average);
            System.out.println("session 7");
            if (Double.compare(average, 0.0) != 0) {
                upsellingRate = (last - average) / average * 100;
            }
        }
        System.out.println("upselling rate " + upsellingRate);
        return upsellingRate;
    }
}

class ValueComparatorInt implements Comparator {

    Map base;

    public ValueComparatorInt(Map base) {
        this.base = base;
    }

    @Override
    public int compare(Object a, Object b) {

        if ((Integer) base.get(a) < (Integer) base.get(b)) {
            return 1;
        } else if ((Integer) base.get(a) == (Integer) base.get(b)) {
            return 0;
        } else {
            return -1;
        }
    }
    //Hieu-end 
}
